﻿package org.baicaix.utils {
	import flash.utils.Endian;	
	import flash.utils.ByteArray;

	/**
	 * 2009.16.16	tamt	增加writeINT方法
	 * 二进制相关处理
	 */
	public class Xba {
		public var  types : Array;
		public var wTypes : Array;
		private var spaceArray : Array;
		//存0字符串的数组
		private var zeroArray : Array;
		public static const BYTE : String = 'byte';
		public static const CHAR : String = 'CHAR';
		//高级字符串，自动判断字符串长度		public static const CHARAd : String = 'CHARAD';

		public static const DWORD : String = 'DWORD';
		public static const WORD : String = 'WORD';
		public static const REPEAT : String = 'REPEAT';
		public static const SHORT : String = 'SHORT';
		public static const INT : String = 'INT';

		public function  Xba() {
			types = new Array;
			wTypes = new Array;
			
			types[BYTE] = readBYTE; 
			types[CHAR] = readCHAR;			types[CHARAd] = readCharAd;
			types[DWORD] = readDWORD;
			types[WORD] = readWORD;
			types[REPEAT] = readREPEAT;
			types[SHORT] = readSHORT;
			types[INT] = readINT;
			
			wTypes[BYTE] = writeBYTE;
			wTypes[DWORD] = writeDWORD;
			wTypes[CHAR] = writeCHAR;
			wTypes[CHARAd] = writeCharAdvance;
			wTypes[WORD] = writeWORD;
			wTypes[REPEAT] = writeREPEAT;
			wTypes[SHORT] = writeSHORT;
			wTypes[INT] = writeINT;
			var s : String = '';
			spaceArray = new Array;
			for( var n : int = 0;n < 256;n++ ) {
				spaceArray[n] = s;
				s += ' ';
			}
			var s1 : String = '';
			zeroArray = new Array;
			for (var i : uint = 0;i < 10;i++) {
				zeroArray[i] = s1;
				s1 += '0';
			}
		}

		/**
		 * 检查数据长度是否正确
		 * 暂时支持byte
		 */
		public function checkLength(ba : ByteArray,type : String,num : uint) : Boolean {
			if(type == BYTE) {
				return ba.length == num;
			}else if(type == INT) {
				return ba.length == num * 4;
			}
			return false;
		}

		public function writeBYTE(ba : ByteArray,data : uint) : void {
			ba.writeByte(data);
		}

		/**
		 * 如果l不等于0加入空格到l长度
		 * @param ba
		 * @param text
		 * @param l
		 * 
		 */		
		public function writeCHAR(ba : ByteArray,s : String,l : uint = 0) : void {
			if(l == 0) {
				ba.writeMultiByte(s, 'utf-8');
			} else {
				if( s.length > l )
				s = s.substr(0, l);
				else
				s += spaceArray[l - s.length];
				ba.writeMultiByte(s, 'utf-8');
			}
		}

		/**
		 * 高级写入字符串，写入字符串长度，和字符串本身，utf-8
		 */
		public function writeCharAdvance(ba : ByteArray,s : String) : void {
			var l : uint = ba.length;
			ba.writeByte(l);
			//l = ba.position;
			ba.writeMultiByte(s, 'utf-8');
			//字符串长度+一个byte长度
			l = ba.length - l;
			//ba位置移到写入之前
			ba.position = ba.position - l;
			ba.writeByte(l - 1);
			ba.position = ba.position + l - 1;
		}

		public function writeDWORD(ba : ByteArray,data : uint) : void {
			ba.writeUnsignedInt(data);
		}

		public function writeWORD(ba : ByteArray,data : int) : void {
			ba.writeShort(data);
		}

		public function writeSHORT(ba : ByteArray,data : int) : void {
			ba.writeShort(data);
		}

		
		public function writeINT(ba : ByteArray,data : int) : void {
			ba.writeInt(data);
		}

		public function writeREPEAT(ba : ByteArray,wLenth : uint,repeatTypes : Array,data : Array) : void {
			var i : int,j : int; 
			i = 1;
			var rl : uint = repeatTypes.length;
			for(j = 0;j < wLenth;j++) {
				for(i = 0;i < rl;i++) {
					wTypes[repeatTypes[i]](ba, data[j][i]);
				}
			}
		}

		/*public static function getInstance() : Xba {
		if(instance == null) {
		instance = new Xba;
		}
		return instance;
		}*/

		public function readBYTE(ba : ByteArray) : uint {
			return ba.readUnsignedByte();
		}

		/**
		 * 新加的高级读取字符串,先读取一个字符串长度，然后是字符串
		 */
		public function readCharAd(ba : ByteArray) : String {
			var l : uint = readBYTE(ba);
			//trace('读取字符串长度=', l);
			return readCHAR(ba, l);
		}

		public function readCHAR(ba : ByteArray,l : int = -1,charSet : String = 'utf-8') : String {
			var result : String = '';
			if(l == -1) {
				result = ba.readMultiByte(ba.bytesAvailable, charSet);
			}else if(l < -1) {
				throw new Error('读取字符串长度不能为负！');
			} else {
				result = ba.readMultiByte(l, charSet);
			}
			return result;
		}

		public function readDWORD(ba : ByteArray) : uint {
			return ba.readUnsignedInt();
		}

		public function readUint(ba : ByteArray) : uint {
			return ba.readUnsignedInt();
		}

		public function readINT(ba : ByteArray) : int {
			return ba.readInt();
		}

		public function readWORD(ba : ByteArray) : uint {
			return ba.readUnsignedShort();
		}

		public function readSHORT(ba : ByteArray) : int {
			return ba.readShort();
		}

		public function readREPEAT(ba : ByteArray,reapeatLen : uint,repeatTypes : Array) : Array {
			var t : Array = [];
			var l : uint = repeatTypes.length;
			var j : int,i : int;
			var t_temp : Array;
			for(j = 0;j < reapeatLen;j++) {
				t_temp = [];
				for(i = 0;i < l;i++) {
					t_temp.push(types[repeatTypes[i]](ba));
				}
				t.push(t_temp);
			}
			return t;
		}

		/**
		 * uint数字转16进制格式字符串,空格补在前面
		 * @param inputUint 输入的uint数字
		 * @param l 转换后的字符串长度，默认为8
		 * 
		 */
		public function getUintToString(inputUint : uint,l : uint = 8) : String {
			var t : String = inputUint.toString(16);
			if(t.length > l) {				
				throw new Error('转换后字符串长度超出限定!');
			}
			t = zeroArray[l - t.length] + t;
			return t;
		}

		/**
		 *  得到数的二进制的某一位是否为1
		 *  @param i 原数字
		 *  @param bitNum 第几位
		 */
		public static function getBit(i : uint,bitNum : uint) : Boolean {
			return (i & (1 << bitNum)) != 0;
		}

		/**
		 * 把数字某位改写为1或0
		 *@param i 原数字
		 *@param bitNum 第几位
		 *@param have true 为写为1，false为0 
		 */
		public static function setBit(i : uint,bitNum : uint,have : Boolean = true) : uint {
			var t : uint = i;
			if(have)
			t |= (1 << bitNum);
			else
			t ^= t & (1 << bitNum);
			/*if(getBit(i, bitNum) == have)return;
			else*/ 
			return t;
		}

		/**
		 * 得到ba是否到了末端
		 */
		public static function getByteArrayNotEnd(ba : ByteArray) : Boolean {
			return ba.position < ba.length;
		}

		//--------------其它处理s--------------
		
		//--------------其它处理e--------------

		public function getBA() : ByteArray {
			var byteArray : ByteArray = new ByteArray();
			byteArray.endian = Endian.LITTLE_ENDIAN;
			return byteArray;
		}

		/**
		 * 得到字符串二进制长度 基于utf-8
		 */
		public  function getStringBytes(str : String) : uint {
			var ba : ByteArray = new ByteArray();
			ba.writeMultiByte(str, "utf-8");
			return ba.length;
		}
	}
}